package common;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

public class Utils
{
    public static long DAILY_SEC=86400L;
    
    public static long DAILY_MIL_SEC=86400000L;
    
    public static long DAILY_HOUR=3600;
    
    public static long DAILY_MIL_HOUR=3600000;
    
    
    static public String formatDate(Date date)
    {
        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSS").format(date);
    }
    static public String convertToDayHourMinuteSecondMillisecondFixedFormat(long span)
    {
        long days = span / DAILY_MIL_SEC;
        span = span % DAILY_MIL_SEC;
        long hours = span / DAILY_MIL_HOUR;
        span = span % DAILY_MIL_HOUR;
        long minutes = span / 60000 ;
        span = span % 601000;
        long seconds = span / (1000);
        span = span % 1000;
        long millis = span;

        return days+" "+hours+":"+minutes+":"+seconds+"."+millis;
    }
    static public String convertToDayHourMinuteSecondMillisecondShortFormat(long span)
    {
        long days = span / (1000 * 60 * 60 * 24);
        span = span % (1000 * 60 * 60 * 24);
        long hours = span / (1000 * 60 * 60);
        span = span % (1000 * 60 * 60);
        long minutes = span / (1000 * 60);
        span = span % (1000 * 60);
        long seconds = span / (1000);
        span = span % 1000;
        long millis = span;

        StringBuilder sb=new StringBuilder();
        if (days > 0)
        {
            sb.append(days);
            sb.append(" d,");
        }
        if (hours > 0)
        {
            sb.append(hours);
            sb.append(" h,");
        }
        if (minutes > 0)
        {
            sb.append(minutes);
            sb.append(" m:");
        }
        sb.append(seconds);
        sb.append(" s:");
        sb.append(millis);
        sb.append(" ms");
        return sb.toString();

    }
    static public String convertToDayHourMinuteSecondMillisecondLongFormat(long span)
    {
        long days = span / (1000 * 60 * 60 * 24);
        span = span % (1000 * 60 * 60 * 24);
        long hours = span / (1000 * 60 * 60);
        span = span % (1000 * 60 * 60);
        long minutes = span / (1000 * 60);
        span = span % (1000 * 60);
        long seconds = span / (1000);
        span = span % 1000;
        long millis = span;

        StringBuilder sb=new StringBuilder();
        if (days > 0)
        {
            sb.append(days);
            sb.append(" days, ");
        }
        if (hours > 0)
        {
            sb.append(hours);
            sb.append(" hours, ");
        }
        if (minutes > 0)
        {
            sb.append(minutes);
            sb.append(" minutes,");
        }
        sb.append(seconds);
        sb.append(" seconds, ");
        sb.append(millis);
        sb.append(" milliseconds");
        return sb.toString();

    }
    
    public static String getLocalHostName() throws UnknownHostException
    {
        //If this call fails with security exception and you are using Linux, go to /etc/host and
        // enter the correct host name for 127.0.0.1
        return java.net.InetAddress.getLocalHost().getHostName();
    }
    public static String getLocalHostAddress() throws UnknownHostException
    {
        //If this call fails with security exception and you are using Linux, go to /etc/host and
        // enter the correct host name for 127.0.0.1
        return java.net.InetAddress.getLocalHost().getHostAddress();
    }
    public static String getCharset(String contentType)
    {
        if (contentType != null)
        {
            for (String part : contentType.split(";"))
            {
                String[] pairs = part.split("=");
                if (pairs[0].trim().equalsIgnoreCase("charset"))
                {
                    return pairs[1].trim().toUpperCase();
                }
            }
        }
        return "UTF-8";
    }


    // This class saves us a copy when reading to end of stream without knowing the stream length
    // beforehand.
    static public class ByteArrayStreamContent
    {
        private final byte[] content;
        private final int  size;

        public byte[] getContent()
        {
            return content;
        }

        public int getSize()
        {
            return size;
        }

        public ByteArrayStreamContent(byte[] content, int size)
        {
            this.content = content;
            this.size = size;
        }
    }

    static public ByteArrayStreamContent readToEnd(InputStream inputStream, int lengthEstimate) throws IOException
    {
        byte[] buffer = new byte[lengthEstimate];
        int size = 0;
        while (true)
        {
            int length = inputStream.read(buffer, size, buffer.length - size);
            if (length == -1)
            {
                break;
            }
            size += length;
            if (size < buffer.length)
            {
                continue;
            }
            byte[] newBuffer = new byte[buffer.length * 2];
            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
            buffer = newBuffer;
        }
        return new ByteArrayStreamContent(buffer, size);
    }

    public static byte[] read(InputStream inputStream, int length) throws IOException 
    {
    	  byte[] buffer = new byte[length];
        int bytesRead = 0;
        int readCalls=0;
        try
        {
            while (bytesRead < length)
            {
                int bytes = inputStream.read(buffer, bytesRead, length - bytesRead);
                readCalls++;
                if (bytes == -1)
                {
                    break;
                }
                bytesRead += bytes;
            }
        }
        catch (IOException ex)
        {
            if (bytesRead!=length)
            {
                throw new IOException("IOException, Desired length=" + length + ", actual read=" + bytesRead + ", readCalls=" + readCalls, ex);
            }
        }
        if (bytesRead!=length)
        {
            throw new IOException("Inconsistency, Desired length=" + length + ", actual read=" + bytesRead + ", readCalls=" + readCalls);
        }
        return buffer;
    }

    public static String getStackTrace(Throwable throwable)
    {
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        throwable.printStackTrace(printWriter);
        return writer.toString();
    }

    /*
     * The idea is that we want ops to be able to specify a precise path relative from baseDirectory
     * or from the absolute root. The concept of baseDirectory is similar to the 'current directory'
     * concept, the reason for not using current directory is that the app does not want to fight
     * the app container over the control of the current directory. If the path parameter starts
     * with seperatorChar, or in the case of Windows, includes a driver letter (eg 'c:\myidr'), then
     * baseDirectory is not prepended to the path. This permits the operator to specify absolute
     * dedicated paths, for example, the operator may have SAN drive just for logging. Finally, the
     * canonical version of the assembled path is returned, so the app can print it out to allow the
     * operator to verify what path is really used.
     */
    public static String getPlatformAdjustedCanonicalPath(String baseDirectory, String path) throws IOException
    {
        if (File.separatorChar == '\\') // windows
        {
            path = path.replace('/', File.separatorChar);

            // If path starts with '/', or includes a drive letter, we consider it a absolute path
            if ((path.indexOf(":") > 0) || (path.indexOf(File.separatorChar) == 0))
            {
                return new File(path).getCanonicalPath();
            }
        }
        else
        {
            path = path.replace('\\', File.separatorChar);
            // If path starts with '/', we consider it a absolute path.
            if (path.indexOf(File.separatorChar) == 0)
            {
                return new File(path).getCanonicalPath();
            }
        }
        path = baseDirectory + File.separatorChar + path;
        return new File(path).getCanonicalPath();
    }

    public static String readToEnd(BufferedReader reader) throws IOException
    {
        StringBuffer buffer = new StringBuffer();
        char[] array = new char[65536];
        while (true)
        {
            int size = reader.read(array, 0, array.length);
            if (size == -1)
            {
                break;
            }
            buffer.append(array, 0, size);
        }
        return buffer.toString();
    }

    public static String readToEnd(String file) throws IOException
    {
        BufferedReader reader = new BufferedReader(new FileReader(file));
        try
        {
            StringBuffer buffer = new StringBuffer();
            char[] array = new char[65536];
            while (true)
            {
                int size = reader.read(array, 0, array.length);
                if (size == -1)
                {
                    break;
                }
                buffer.append(array, 0, size);
            }
            return buffer.toString();
        }
        finally
        {
            reader.close();
        }
    }

    public static String generateParameterPlaceHolders(int number,String placeHolder)
    {
        StringBuilder sb = new StringBuilder();
        if (number > 0)
        {
            sb.append(placeHolder);
            for (int i = 1; i < number; i++)
            {
                sb.append(',').append(placeHolder);
            }
        }
        return sb.toString();
    }

    public static String generateSQLParameterPlaceHolders(int number)
    {
        return generateParameterPlaceHolders(number, "?");
    }
    
    public static Object[] toObjectArray(String[] array)
    {
    	Object[] objects=new Object[array.length];
    	for (int i=0;i<array.length;i++)
    	{
    		objects[i]=array[i];
    	}
    	return objects;
    }

    public static Object[] toObjectArray(List<?> list)
    {
    	Object[] objects=new Object[list.size()];
    	return list.toArray(objects);
    }
    public static String generateRandomCodeForFormSubmit()
    {
        return Integer.toString(new Random().nextInt(900) + 100);
    }
}
